<!-- 发布订阅者模式与观察者模式的区别在于：发布订阅者模式有事件总线 -->
<script>
  class Observer {
    constructor() {
      // 消息队列，及事件总线的概念
      this.message = {}
    }
    // 订阅
    $on(type,fn){
      if(!this.message[type]) {
        this.message[type] = []
      }
      this.message[type].push(fn)
    }
    // 发布
    $emit(type,data){
      if(!this.message[type]) return;
      for(let i = 0; i < this.message[type].length; i++) {
        const fn = this.message[type][i]
        fn(data)
      }
    }
    // 取消
    $off(type) {
      if(this.message[type]) this.message[type] = undefined
    }
    // 只订阅一次，及订阅后就取消
    $once(type,fn){
      this.$on(type,()=>{
        fn()
        this.$off(type)
      })
    }
  }
</script>